(*  :Title:	Stacks and Queues  *)

(*  :Authors:	Brian Evans, James McClellan  *)

(*  :Summary:	To provide stack and queue structures  *)

(*  :Context:	SignalProcessing`ObjectOriented`StackQueue`  *)

(*  :PackageVersion:  2.7	*)

(*
    :Copyright:	Copyright 1989-1991 by Brian L. Evans
		Georgia Tech Research Corporation

	Permission to use, copy, modify, and distribute this software
	and its documentation for any purpose and without fee is
	hereby granted, provided that the above copyright notice
	appear in all copies and that both that copyright notice and
	this permission notice appear in supporting documentation,
	and that the name of the Georgia Tech Research Corporation,
	Georgia Tech, or Georgia Institute of Technology not be used
	in advertising or publicity pertaining to distribution of the
	software without specific, written prior permission.  Georgia
	Tech makes no representations about the suitability of this
	software for any purpose.  It is provided "as is" without
	express or implied warranty.
 *)

(*  :History:	*)

(*  :Keywords:	*)

(*  :Source:	*)

(*  :Warning:	*)

(*  :Mathematica Version:  1.2 or 2.0  *)

(*  :Limitation:  *)

(*  :Discussion:  *)

(*
    :Functions:	  ClearQueue
		  ClearStack
		  Dequeue
		  Enqueue
		  Pop
		  Push
		  TopElement
 *)



(*  B E G I N     P A C K A G E  *)

BeginPackage[ "SignalProcessing`ObjectOriented`StackQueue`" ]


If [ TrueQ[ $VersionNumber >= 2.0 ],
     $NewMessage[ System`General, "spell" ];
     $NewMessage[ System`General, "spell1" ];
     Off[ General::spell ];
     Off[ General::spell1 ] ];


(*  U S A G E     I N F O R M A T I O N  *)

ClearQueue::usage =
	"ClearQueue[q] sets q to be an empty queue."

ClearStack::usage =
	"ClearStack[s] sets s to be an empty stack."

Dequeue::usage =
	"Dequeue[queue, element] removes element from the queue."

Enqueue::usage =
	"Enqueue[queue, element] adds element to the queue."

Pop::usage =
	"Pop[stack] removes and returns the value at the top of the stack."

Push::usage =
	"Push[stack, element] adds the element to the top of the stack."

Queue::usage =
	"Object head for a queue structure."

TopElement::usage =
	"TopElement[packet] returns the first element in the data packet. \
	This is the top of the stack if packet is a stack. \
	This is the next in the queue if packet is a queue. \
	The packet remains unaltered."

(*  E N D     U S A G E     I N F O R M A T I O N  *)


Begin[ "`Private`" ]


(*  Q U E U E     R O U T I N E S  *)

SetAttributes[ClearQueue, {HoldFirst}]
SetAttributes[Dequeue, {HoldFirst}]
SetAttributes[Enqueue, {HoldFirst}]


ClearQueue[queue_] := queue = Queue[];

Dequeue[queue_, element_] := Null	/; EmptyQ[queue]
Dequeue[queue_, element_] :=
	Block [	{index, pos},
		pos = 0;
		sametest[x_] := If [ SameQ[x, element], Return[pos], ++pos ];
		Scan[sametest, queue];
		If [ pos > 0,
		     queue = Drop[queue, {pos, pos}] ];
		queue ]

Enqueue[queue_, element_] := AppendTo[queue, element]


(*  S T A C K     R O U T I N E S  *)

SetAttributes[ClearStack, {HoldFirst}]
SetAttributes[Pop, {HoldFirst}]
SetAttributes[Push, {HoldFirst}]

ClearStack[stack_] := stack = Stack[];

Pop[stack_] := Null		/; EmptyQ[stack]
Pop[stack_] :=
	Block [ {newstack},
		topelement = TopElement[stack];
		stack = Rest[stack];
		topelement ]

Push[stack_, element_] := PrependTo[stack, element]


(*  G E N E R A L I Z E D     R O U T I N E S  *)

TopElement[x_] := Null		/; AtomQ[x]
TopElement[h_[]] := Null
TopElement[h_[values__]] := h[values][[1]]


(*  E N D     P A C K A G E  *)

End[]
EndPackage[]

If [ TrueQ[ $VersionNumber >= 2.0 ],
     On[ General::spell ];
     On[ General::spell1 ] ];


(*  E N D I N G     M E S S A G E  *)

Print["Stack and queue structures successfully loaded."]
Null
